import { error as err, success } from '@cydon/ui/Message'
import { API } from '../api'

/** 从对象中获取指定前缀的方法 */
export type MethodsStartsWith<T, Prefix extends string> = {
	[K in keyof T as K extends `${Prefix}${infer Method}` ? Method : never]:
	T[K] extends (...args: any[]) => any ? T[K] : never
}

/** 从对象中获取公共键 */
export type CommonKeys<T, U> = keyof T & keyof U

export const onHashChange = (cb: (name: string) => void) => {
	const f = () => cb(location.hash.slice(1))
	f()
	addEventListener('hashchange', f)
}

export type DateLike = bigint | boolean | number | string | Date

/** 将时间转换为Unix时间戳 */
export const convertTime = (time: DateLike) =>
	(BigInt(time) + 621_355_968_000_0n) * 1000n

/** 时间到现在的天数
 * @param time 时间
 * @returns 天数
 */
export const getDays = (time: number) => (+new Date - time) / 864e5

/** 阻止默认行为并停止冒泡 */
export const prevent = (e: Event) => {
	e.stopPropagation()
	e.preventDefault()
}

/** 防抖 */
export const debounce = <T extends (...args: any[]) => any>(fn: T, delay = 250) => {
	let timer: NodeJS.Timeout
	return function (this: ThisParameterType<T>, ...args: Parameters<T>) {
		clearTimeout(timer)
		timer = setTimeout(() => fn.apply(this, args), delay)
	} as T
}

/** 通用错误处理 */
export const error = (e: string | Error) => {
	if (typeof e == 'string')
		e = new Error(e)

	// 显示错误信息
	err(e.message)
	// TODO: 错误处理
	throw e
}

/**
 * 从多个URL导入模块
 * @param urls URL列表
 */
export async function importM(urls: string[]) {
	const controller = new AbortController,
		{ blob } = await Promise.any(urls.map(async (url, i) => {
			const resp = await fetch(url, { signal: controller.signal })
			if (!resp.ok)
				throw new Error(resp.statusText)
			return { i, blob: await resp.blob() }
		}))
	controller.abort()
	const url = URL.createObjectURL(blob)
	setTimeout(URL.revokeObjectURL, 3000, url)
	return import(/* @vite-ignore */url)
}


/** 上传文件 */
export function upload(files: string[]) {
	const p = []
	for (const file of files) {
		let url = file.replace(/\\/g, '/')
		if (!url.startsWith('file://'))
			url = 'file:///' + url
		// 编码非ASCII字符
		const normalized = /[^\0-\x7F]|%/.test(url) ? encodeURI(url) : url
		p.push(API.post(normalized).then((id) => {
			success(`上传成功，ID:${id} ${url}`)
		}, e => error(`上传失败 ${url} ${e.message}`)))
	}
	return Promise.all(p)
}

declare global {
	interface BigIntConstructor {
		(value: bigint | boolean | number | string | Date): bigint
	}
}
